import json
import logging
import platform
import uuid
from common import Authorization, DynamoDBKayValue, MusicServiceS3, Request, Response
import os
import requests
from configuration import is_running_on_aws_lambda
from mutagen import File as MutagenFile

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
if not is_running_on_aws_lambda():
    handler = logging.StreamHandler()
    # format the log
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)

def lambda_handler(event: dict, context):
    is_login, user_info = Authorization.get_user_info(event)
    if not is_login:
       return user_info
   
    query = event.get('queryStringParameters', {})
    method = event.get('requestContext', {}).get('http', {}).get('method', 'GET')
    body = event.get('body', {})
    try:
        body = json.loads(body)
    except:
        pass
    
    method_handler = {
        'GET': handle_get,
        'POST': handle_post,
        'PUT': handle_put,
        'DELETE': handle_delete,
    }
    
    return method_handler[method](query, user_info, body)

def handle_get(query: dict, user_info: dict, body: dict):
    id = query.get('id', None)
    url = query.get('url', None)
    if url:
        logger.info(f"获取音乐信息: {url}")
        return handle_get_music_by_url(url, user_info)
    if id:
        logger.info(f"获取音乐信息: {id}")
        return handle_get_music_by_id(id, user_info)
    
    logger.info(f"获取所有音乐信息")
    return handle_list_music(user_info)

def handle_list_music(user_info: dict):
    music_service_s3 = MusicServiceS3(user_info)
    music_list = music_service_s3.list_all_music()
    return Response.build_success_response(music_list)
    
def handle_get_music_by_id(id: str, user_info: dict):
    music_service_s3 = MusicServiceS3(user_info)
    music_info = music_service_s3.get_music_by_id(id)
    if music_info:
        logger.info(f"从S3获取音乐信息: {music_info}")
        return Response.build_success_response(music_info)
    
    music_info = DynamoDBKayValue.get_music_value(id)
    if not music_info:
        logger.info(f"一个不存在的音乐资源: {id}")
        return Response.build_error_response(f"一个不存在的音乐资源")
    
    music_info['isLike'] = False
    music_service_s3.set_music_by_id(id, music_info)
    logger.info(f"保存音乐信息到S3: {music_info}")
    return Response.build_success_response(music_info)

def handle_get_music_by_url(url: str, user_info: dict):
    """
    下载指定url的音乐到Lambda临时目录，解析音乐的作者、名字、大小、音质等信息
    """
    music_service_s3 = MusicServiceS3(user_info)
    music_info = music_service_s3.get_music_by_url(url)
    if music_info:
        logger.info(f"从S3获取音乐信息: {music_info}")
        return Response.build_success_response(music_info)
    
    # 生成新的ID
    id = str(uuid.uuid4())

    try:
        # Lambda临时目录
        tmp_dir = '/tmp'
        if not os.path.exists(tmp_dir):
            os.makedirs(tmp_dir)
        
        # 获取文件名
        filename = url.split('/')[-1]
        if not filename:
            filename = 'music_file'
        file_path = os.path.join(tmp_dir, filename)
        
        # 下载文件
        headers = {
            'User-Agent': 'Mozilla/5.0 (compatible; MusicBot/1.0)'
        }
        resp = requests.get(url, headers=headers, stream=True, timeout=20)
        if resp.status_code != 200:
            raise Exception(f"下载失败，状态码: {resp.status_code}")
        
        total_size = int(resp.headers.get('Content-Length', 0))
        logger.info(f"开始下载音乐文件，预期大小: {total_size} 字节")
        
        downloaded_size = 0
        with open(file_path, 'wb') as f:
            for chunk in resp.iter_content(chunk_size=8192):
                if chunk:
                    f.write(chunk)
                    downloaded_size += len(chunk)
        
        # 验证下载是否完整
        if downloaded_size == 0:
            raise Exception("下载的文件内容为空")
        
        if total_size > 0 and downloaded_size != total_size:
            logger.warning(f"文件大小不匹配: 预期 {total_size} 字节，实际 {downloaded_size} 字节")
        
        logger.info(f"音乐文件下载完成: {downloaded_size} 字节")
        
        # 解析文件信息
        info = {
            "file_path": file_path,
            "file_name": filename,
            "file_size": downloaded_size,
            "file_size_mb": round(downloaded_size / 1024 / 1024, 2)
        }
        
        # 尝试用mutagen解析音频元数据
        try:
            audio = MutagenFile(file_path, easy=True)
            if audio:
                info['duration'] = int(audio.info.length) if hasattr(audio.info, 'length') else None
                info['bitrate'] = int(audio.info.bitrate / 1000) if hasattr(audio.info, 'bitrate') else None
                info['sample_rate'] = getattr(audio.info, 'sample_rate', None)
                info['channels'] = getattr(audio.info, 'channels', None)
                # 标签信息
                info['title'] = (audio.get('title', [None])[0] if 'title' in audio else None)
                info['artist'] = (audio.get('artist', [None])[0] if 'artist' in audio else None)
                info['album'] = (audio.get('album', [None])[0] if 'album' in audio else None)
            else:
                info['error'] = "无法识别的音频格式"
                logger.error(f"无法识别的音频格式: {file_path}")
        except Exception as e:
            info['error'] = f"元数据解析失败: {str(e)}"
            logger.error(f"元数据解析失败: {str(e)}")
        
        # 删除临时文件
        try:
            os.remove(file_path)
        except Exception:
            pass

    except Exception as e:
        logger.error(f"处理失败: {str(e)}")
        return Response.build_error_response(f"处理失败: {str(e)}")
    
    music_info = {
        "id": id,
        "song": info.get("title", ""),
        "singer": info.get("artist", ""),
        "album": info.get("album", ""),
        "quality": "未知",
        "cover": "https://zhuchundashuaige.s3.eu-north-1.amazonaws.com/public/images/%E6%9C%AA%E7%9F%A5%E9%9F%B3%E4%B9%90.png",
        "interval": "{:02d}分{:02d}秒".format(int(info.get("duration", 0) or 0) // 60, int(info.get("duration", 0) or 0) % 60), 
        "link": f"https://music.zhuchundashuaige.com/#/?id={id}",
        "bps": info.get("bitrate", 0),
        "url": url,
        "type": "import",
        "roma": "",
        "lrc": None,
        "isLike": False,
    }
    music_service_s3.set_music_by_id(id, music_info)
    logger.info(f"保存音乐信息到S3: {music_info}")
    return Response.build_success_response(music_info)

def handle_post(query: dict, user_info: dict, body: dict):
    id = query.get('id', None)
    if not id:
        return Response.build_error_response("id is required")
    music_service_s3 = MusicServiceS3(user_info)
    music_info = music_service_s3.get_music_by_id(id)
    if not music_info:
        return Response.build_error_response("music not found")
    
    platform = music_info.get('type', 'import')
    platform_mapping = {
        'tencent': 'https://api.vkeys.cn/v2/music/tencent?id=',
        'netease': 'https://api.vkeys.cn/v2/music/netease?id=',
    }
    platform_url = platform_mapping.get(platform, None)
    if not platform_url:
        return Response.build_response(music_info)
    
    platform_url = platform_url + id
    resp = Request.make_request_with_retry(platform_url)
    if resp.status_code != 200:
        return Response.build_error_response("get music info failed")
    try:
        data = resp.json().get('data', {})
        code = resp.json().get('code', 500)
        if code >= 500:
            return Response.build_error_response(f"获取音乐信息失败，请重试。错误信息：{resp.json().get('message', '无')}")
        download_url = data.get('url', None)
        if download_url:
            music_info['url'] = download_url
            logger.info(f"get music download url success: {download_url}")
            music_service_s3.set_music_by_id(id, music_info)
            
            DynamoDBKayValue.update_music_value(id, data)
            return Response.build_success_response(music_info)
        else:
            return Response.build_error_response("get music download url failed")
    except Exception as e:
        logger.error(f"parse music info failed: {e}, resp: {resp.text}")
        return Response.build_error_response(f"Do not support this platform: {platform}")

def handle_put(query: dict, user_info: dict, body: dict):
    id = query.get('id', None)
    if not id:
        return Response.build_error_response("id is required")
    music_service_s3 = MusicServiceS3(user_info)
    music_info = music_service_s3.get_music_by_id(id)
    if not music_info:
        return Response.build_error_response("music not found")
    for key, value in body.items():
        if key in music_info:
            music_info[key] = value
    music_service_s3.set_music_by_id(id, music_info)
    return Response.build_success_response(music_info)

def handle_delete(query: dict, user_info: dict, body: dict):
    id = query.get('id', None)
    if not id:
        return Response.build_error_response("id is required")
    music_service_s3 = MusicServiceS3(user_info)
    music_service_s3.delete_music_by_id(id)
    return Response.build_success_response("success")

    